import asyncio
import os
import re

import requests
import webview
from playwright.async_api import async_playwright, Error
from moviepy.editor import VideoFileClip


class JsAPI:
    def __init__(self):
        self.window = None
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
        }
        self.share_text_url_regex = r"(https://v.douyin.com/.*?/)"
        self.folder = os.path.join(os.path.expanduser("~"), "Desktop")
        self.folder_file = os.path.join(os.path.expanduser("~"), "dldy.txt")
        if os.path.exists(self.folder_file):
            with open(self.folder_file, "r") as f:
                self.folder = f.read()

    def init(self):
        self.window = webview.windows[0]

    def select_folder(self):
        self.window = webview.windows[0]
        folder = self.window.create_file_dialog(
            webview.FOLDER_DIALOG
        )

        if folder:
            self.folder = folder[0]
            with open(self.folder_file, "w") as f:
                f.write(self.folder)

        return self.folder

    def get_save_folder(self):
        return self.folder

    def progress(self, progress: int = None, message: str = None):
        if progress:
            self.window.evaluate_js(f"document.getElementById('progress-bar').style.width = '{progress}%'")

        progress_message = ""
        if progress:
            progress_message = f"[{progress}%] "
        if message:
            progress_message += message

        self.window.evaluate_js(f"document.getElementById('progress-message').innerText = '{progress_message}'")

    def download_video(self, share_text, save_folder, convert_sound):
        progress = 0
        self.progress(progress=progress, message="准备下载...")

        if not share_text:
            self.progress(progress=progress, message="请输入抖音分享链接")

        progress += 2
        self.progress(progress=progress, message="检查保存目录中...")

        # 保存目录检查
        if not os.path.exists(save_folder):
            progress += 2
            self.progress(progress=progress, message="目录不存在，创建中...")

            os.makedirs(save_folder)

            progress += 2
            self.progress(progress=progress, message="目录创建完成")

        # 提取链接
        progress += 2
        self.progress(progress=progress, message="提取分享链接中的可访问页面...")

        urls = re.findall(self.share_text_url_regex, share_text)
        if not urls:
            self.progress(progress=progress, message="分享链接中不包含可访问页面")
            self.window.evaluate_js("enable_write()")
            return

        url = urls[0]
        progress = 10
        self.progress(progress=progress, message=f"准备爬取视频页面: {url}")

        async def run(pg):
            video_urls = []
            title = ""

            async with async_playwright() as p:
                pgr = pg

                for i in range(60):
                    browser = await p.firefox.launch(headless=True)
                    page = await browser.new_page()
                    await page.goto(url)

                    pg += 10
                    self.progress(progress=pg, message=f"访问视频页面: {url}")

                    try:
                        await page.locator('source').wait_for(timeout=5000)
                    except Error:
                        pass

                    video_source_elements = await page.query_selector_all("source")
                    for se in video_source_elements:
                        video_url = await se.get_attribute("src")
                        video_urls.append(video_url)
                    title = await page.title()

                    pg += 10
                    self.progress(progress=pg, message=f"提取视频: 《{title}》")

                    await browser.close()
                    if video_urls:
                        break
                    else:
                        pg = pgr
                        self.progress(progress=pg, message=f"[{i + 1}] 视频提取失败，需重试...")

            if not video_urls:
                self.progress(progress=pg, message=f"视频提取多次失败，请稍后再试。")
                self.window.evaluate_js("enable_write()")
                return

            pg += 10
            self.progress(progress=pg, message=f"正在下载视频：{video_urls[0]}")

            save_path = os.path.join(save_folder, f"{title}.mp4")

            for video_url in video_urls:
                req = requests.get("https:" + video_url, headers=self.headers)

                if req.status_code == 200:
                    with open(save_path, "wb") as f:
                        f.write(req.content)
                    break

            if convert_sound:
                pg = 80
            else:
                pg = 100
                self.window.evaluate_js("enable_write()")
            self.progress(progress=pg, message=f"视频下载完成：{save_path}")

            if convert_sound:
                video_path = save_path
                save_path = os.path.join(save_folder, f"{title}.mp3")
                video_clip = VideoFileClip(video_path)
                video_clip.audio.write_audiofile(save_path)
                video_clip.close()
                pg = 100
                self.progress(progress=pg, message=f"音频转换完成：{save_path}")
                self.window.evaluate_js("enable_write()")

        return asyncio.run(run(progress))


if __name__ == "__main__":
    current_dir = os.path.dirname(os.path.abspath(__file__))
    html_file_path = os.path.join(current_dir, "assets", "index.html")
    icon_path = os.path.join(current_dir, "assets", "favicon.ico")

    webview.create_window(
        title="抖音视频下载器",
        url=html_file_path,
        width=500,
        height=230,
        resizable=False,
        js_api=JsAPI()
    )
    webview.start(
        icon=icon_path
    )
    # $env:PLAYWRIGHT_BROWSERS_PATH=0
    # playwright install firefox
    # pyinstaller --upx-dir D:\app\upx-3.96-win64 --noconfirm --onefile --windowed --icon "D:\code\dyd\assets\favicon.ico" --name "抖音视频下载器" --add-data "D:\code\dyd\assets;assets/"  "D:\code\dyd\app.py"
